home *** CD-ROM | disk | FTP | other *** search
- /* s t d i o l i b
- *
- * (C) Copyright C E Chew
- *
- * Feel free to copy, use and distribute this software provided:
- *
- * 1. you do not pretend that you wrote it
- * 2. you leave this copyright notice intact.
- *
- * This include file is used by the stdio code. It provides some
- * useful macro definitions that make the code a bit easier to
- * write.
- *
- * Patchlevel 1.2
- *
- * Edit History:
- * 06-Sep-1989 Cast first argument of _flsbuf().
- * 05-Sep-1989 Remove dependency on MINIX define. Define P() instead
- * of Prototype() (apparently less distracting). Use
- * atexit() instead of __cleanup for better portability.
- * For ld type loaders, we can use a loader trick
- * and not use an explicit call to atexit thus SETIOFLUSH
- * can be empty (almost).
- * 03-Sep-1989 Added BUFFERSIZE() and altered UNUSEDINBUFFER() to
- * accommodate line buffered streams. Added PUTC()
- * and NPUTC() for non line buffered streams.
- */
-
- #include <stdio.h>
- #include <varargs.h>
- #include <errno.h>
-
- #if defined(__STDC__)
- # if !defined(__NO_PROTO__)
- # define P(x) x
- # else
- # define P(x) ()
- # endif
- #else
- # define P(x) ()
- #endif
-
- void _ioflush P((void)); /* flush output */
- void _ioexit P((void)); /* exit linking function */
- int _allocbuf P((FILE *)); /* internal buffering */
- int _fopen P((CONST char *, CONST char *, int, short *)); /* fopen assist */
- FILE **_slot P((FILE *)); /* find a slot */
- FILE *_file P((FILE *, int, short)); /* initialise FILE */
-
- int atexit P((void (*)(void))); /* specify wrapup */
-
- extern int _wrapstdio; /* stdio wrap required */
- extern int errno; /* system error number */
-
- /* Flag manipulation macros */
-
- #define TESTFLAG(f,x) (((f)->_flag & (x)) != 0)
- #define SETFLAG(f,x) ((f)->_flag |= (x))
- #define CLEARFLAG(f,x) ((f)->_flag &= ~(x))
- #define GETFLAG(f,x) ((f)->_flag & (x))
- #define TOGGLEFLAG(f,x) ((f)->_flag ^= (x))
-
- /* Add _ioflush to exit code
- *
- * Check is _ioflush needs to be added to the exit code. If so then
- * add it. This macro is run time system dependent.
- */
- #if defined(MSDOS)
- # define SETIOFLUSH() { if (_wrapstdio != 0) _wrapstdio = atexit(_ioflush); }
- #endif
-
- #if !defined(SETIOFLUSH)
- # define SETIOFLUSH() _ioexit()
- #endif
-
- /* Putc for non buffered streams
- *
- * This version of putc is explicitly for unbuffered streams. A
- * call is made directly to the buffer flushing code.
- */
- #define NPUTC(x,p) ( _flsbuf((unsigned char)(x),(p)) )
-
-
- /* Putc without line buffering
- *
- * This version of putc() should be exactly the same as that declared
- * in stdio.h except that it shouldn't worry about line buffering.
- */
- #define PUTC(x,p) ( \
- (p)->_ptr < (p)->_base + (p)->_bufsiz \
- ? (int) (*(p)->_ptr++ = (unsigned char)(x)) \
- : _flsbuf((unsigned char)(x),(p)) \
- )
-
- /* Initialise an output buffer
- *
- * This macro uses _base and _bufsiz to initialise _ptr and _end. _ptr
- * will be set to point at the base of the buffer. _end will be set
- * to point at one past the end of the buffer if the stream is buffered
- * otherwise it will point at the base of the buffer. Line buffered
- * streams are considered to be fully buffered.
- */
- #define INITWRITEBUFFER(f) ( \
- (f)->_end = ((f)->_ptr = (f)->_base) + \
- (TESTFLAG(f, _IONBF | _IOLBF) ? 0 : (f)->_bufsiz) \
- )
-
- /* Initialise a buffer to call either _flsbuf or _filbuf
- *
- * This macro initialises the buffer by setting _end and _ptr to
- * _base. This will force the next putc or getc to call the
- * appropriate routine. This is used by the r+, w+ and a+ modes
- * of access.
- */
- #define FLUSHNEXTACCESS(f) ( \
- (f)->_end = (f)->_ptr = (f)->_base \
- )
-
- /* Initialise an output buffer to call _flsbuf
- *
- * This macro initialises the output buffer setting _ptr to _base.
- * _end is set to be _base so that _flsbuf will be called on the
- * next putc.
- */
- #define FLUSHNEXTWRITE(f) ( \
- (f)->_end = (f)->_ptr = (f)->_base \
- )
-
- /* Initialise an input buffer
- *
- * This macro empties an input buffer. It uses _base to initialise
- * _ptr and sets _end to point to the high water mark of the buffer.
- *
- * If the argument v is zero, this macro must have the same effect
- * as a call to FLUSHNEXTACCESS(f).
- */
- #define INITREADBUFFER(f, v) ( \
- (f)->_end = ((f)->_ptr = (f)->_base) + (v) \
- )
-
- /* Initialise a buffer
- *
- * This macro will empty a buffer. It will decide whether it is
- * an input or output buffer by examining _IOWRITE. In the case
- * of a read, _ptr is set so that _filbuf will be called when
- * the stream is next read. In the case of a write, the
- * buffer is initialised so that it can be used for writing.
- *
- * Note that streams opened for update will be set as if they
- * were opened for reading.
- */
- #define INITBUFFER(f) ( \
- TESTFLAG((f), _IOWRITE) ? INITWRITEBUFFER((f)) \
- : INITREADBUFFER((f), 0) \
- )
-
- /* Buffer size
- *
- * Return the size of the output buffer. This will return rubbish
- * for unbuffered streams. Line and fully buffered streams will
- * have the true buffer size returned.
- */
- #define BUFFERSIZE(f) ( (f)->_bufsiz )
-
- /* Bytes left in input buffer
- *
- * This macro returns the number of bytes left in an input buffer.
- */
- #define BYTESINREADBUFFER(f) ( (f)->_end - (f)->_ptr )
-
- /* Bytes written in output buffer
- *
- * This macro returns the number of bytes left in an output buffer.
- */
- #define BYTESINWRITEBUFFER(f) ( (f)->_ptr - (f)->_base )
-
- /* Unused bytes in output buffer
- *
- * This macro returns the number of unused bytes in an output buffer.
- * Unbuffered streams will return rubbish. Line and fully buffered streams
- * will have the amount of space remaining returned.
- */
- #define UNUSEDINWRITEBUFFER(f) ( (f)->_bufsiz - ((f)->_ptr - (f)->_base) )
-
- /* Get pointer into write buffer
- *
- * This macro gets the pointer into the write buffer.
- */
- #define GETWRITEPTR(f) ( (f)->_ptr )
-
- /* Set pointer into write buffer
- *
- * This macro sets the pointer into the write buffer.
- */
- #define SETWRITEPTR(f,p) ( (f)->_ptr = (p) )
-
- /* Get pointer into read buffer
- *
- * This macro gets the pointer into the read buffer.
- */
- #define GETREADPTR(f) ( (f)->_ptr )
-
- /* Set pointer into read buffer
- *
- * This macro sets the pointer into the read buffer.
- */
- #define SETREADPTR(f,p) ( (f)->_ptr = (p) )
-
- /* Check if buffering has been set
- *
- * Return true if buffering has already been set. A stream
- * set for unbuffered output is considered to have had
- * its buffering set.
- */
- #define HASBUFFER(f) ( (f)->_base != 0 )
-
- /* Unroll a loop
- *
- * Assume that the loop must execute at least once. The first argument
- * is the name of the loop control variable. The second argument is
- * the expression to be placed in the loop body. The control variable
- * should be unsigned, otherwise the right shift might propagate the sign
- * bit. The caller must also provide the name of a unique label.
- */
- # define UNROLL_DO(l,v,x) { \
- char t = (v); \
- (v) = ((v)+1) >> 1; \
- if (t & 1) goto l; \
- do { x; l: x; } while (--(v)); \
- }
-